using Devil;
using UnityEngine;

namespace GameToolkit.ContentProvider
{
    [System.AttributeUsage(System.AttributeTargets.Field)]
    public class DeclareTextReferenceAttribute : PropertyAttribute
    {
        public string Declaration { get; set; }
        public int TextAreaHeight { get; set; }
        public bool PerAssetDeclare { get; set; }

        public DeclareTextReferenceAttribute() { PerAssetDeclare = true; }
    }

    [System.Serializable]
    public struct TextReference : System.IEquatable<TextReference>
    {
        public static int GetDeclareID(string text, string declare = null, string guid = null)
        {
            var id = string.IsNullOrEmpty(guid) ? ParallelUtils.ToHash(text) : ParallelUtils.ToHash(guid);
            if (string.IsNullOrEmpty(declare))
                return id;
            else
                return MathExt.Hash(ParallelUtils.ToHash(declare), ':', id);
        }

        public static TextReference Declare(string text, string declare = null, string guid = null)
        {
            TextReference txt;
            txt._txt = text;
            txt._id = GetDeclareID(text, declare, guid);
            return txt;
        }

        //[HideInInspector]
        [SerializeField]
        int _id;
        //[HideInInspector]
        [SerializeField]
        private string _txt;
        public int id => _id;
        public bool isEmpty => _id == 0 && string.IsNullOrEmpty(_txt);
        public string text => _txt;

        public TextReference(int id)
        {
            this._id = id;
            this._txt = "";
        }

        public TextReference(int id, string src)
        {
            this._id = id;
            this._txt = src;
        }

        public TextRes Res
        {
            get
            {
                var tid = id;
                return tid == 0 ? null : TextRes.GetText(tid, null);
            }
        }

        public string AudioRes => TextRes.GetVoice(id, null);

        public static implicit operator string(TextReference txt)
        {
            return txt.ToString();
        }

        public static explicit operator TextReference(string txt)
        {
            var v = new TextReference(0, txt);
            return v;
        }

        public override string ToString()
        {
            return ToString(null);
        }

        public string ToString(TableSet<TextRes> table)
        {
            var tid = id;
            if (tid == 0)
                return _txt;
            try
            {
                var v = table == null ? null : table[tid];
                if (v != null)
                    return v.text;
                v = TextRes.GetText(tid, table);
                return v == null ? _txt : v.text;
            }
            catch (System.Exception e)
            {
                Debug.LogWarning(e);
                return _txt;
            }
        }

        public bool Equals(TextReference other)
        {
            return this.GetHashCode() == other.GetHashCode();
        }

        public override int GetHashCode()
        {
            var hash = _id;
            if (hash == 0)
                hash = _txt == null ? 0 : _txt.GetHashCode();
            return hash;
        }
    }
}